#pragma once

#include "common.h"

enum ProcessorArchitecture
{
	X86,
	X64,
	ARM,
	ITANIUM,
	UNKNOWN
};

enum ProcessorFeatures
{
	MMX = 1,
	SSE = 2,
	SSE2 = 4,
	SSE3 = 8,
	_3D_NOW = 16
};

struct CPUInfo
{
	ProcessorArchitecture architecture;
	u8 features;
	u8 numProcessors;
	u8 numLogicalProcessors;
	u32 mhz;
};

class SysCPU
{
public:
	CPUInfo GetCPUInformation();
};

inline CPUInfo SysCPU::GetCPUInformation()
{
	CPUInfo info;
	info.features = 0;
	SYSTEM_INFO systemInfo;
	HKEY hKey;
	LONG result;
	DWORD data = 0;
	DWORD dataSize = 4;

	GetSystemInfo(&systemInfo);

	switch(systemInfo.wProcessorArchitecture)
	{
	case PROCESSOR_ARCHITECTURE_AMD64:
		info.architecture = X64;
		break;
	case PROCESSOR_ARCHITECTURE_INTEL:
		info.architecture = X86;
		break;
	default:
		info.architecture = UNKNOWN;
	}


	if(IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE))
		info.features |= _3D_NOW;

	if(IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
		info.features |= MMX;

	if(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE))
		info.features |= SSE;

	if(IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE))
		info.features |= SSE2;

	if(IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE))
		info.features |= SSE3;

	info.numLogicalProcessors = static_cast<u8>(systemInfo.dwNumberOfProcessors);

	//! TODO: Fix this //
	info.numProcessors = 0;


	//Check processor speed from registry
	result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0, KEY_READ, &hKey);

	if(result != ERROR_SUCCESS)
	{
		Con::Write("Can't read processor speed from registry");
		info.mhz = 0;
	}
	else
	{
		result = RegQueryValueEx(hKey, TEXT("~MHz"), NULL, NULL, (LPBYTE)&data, &dataSize);

		if(result == ERROR_SUCCESS)
			info.mhz = data;

		RegCloseKey(hKey);
	}


	return info;
}